home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / bash-1.12 / dist / getcwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-12  |  4.1 KB  |  182 lines

  1. /* Copyright (C) 1991 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 1, or (at your option)
  7. any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with the GNU C Library; see the file COPYING.  If not, write to
  16. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <errno.h>
  19. #include <limits.h>
  20. #include <stddef.h>
  21. #include <dirent.h>
  22. #include <unistd.h>
  23. #include <sys/types.h>
  24. #include "maxpath.h"
  25. #include <sys/stat.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28.  
  29. #if !defined (PATH_MAX)
  30. #  if defined (_POSIX_PATH_MAX)
  31. #    define PATH_MAX _POSIX_PATH_MAX
  32. #  else
  33. #    if defined (MAXPATHLEN)
  34. #      define PATH_MAX MAXPATHLEN
  35. #    else
  36. #      define PATH_MAX 255
  37. #    endif
  38. #  endif
  39. #endif
  40.  
  41. /* Get the pathname of the current working directory,
  42.    and put it in SIZE bytes of BUF.  Returns NULL if the
  43.    directory couldn't be determined or SIZE was too small.
  44.    If successful, returns BUF.  In GNU, if BUF is NULL,
  45.    an array is allocated with `malloc'; the array is SIZE
  46.    bytes long, unless SIZE <= 0, in which case it is as
  47.    big as necessary.  */
  48. #ifdef __STDC__
  49. char *getcwd(char *buf, int size) /* from <sys/unistd.h> */
  50. #else
  51. char *
  52. getcwd (buf, size)
  53.      char *buf;
  54.      size_t size;
  55. #endif
  56. {
  57.   dev_t rootdev, thisdev;
  58.   ino_t rootino, thisino;
  59.   char path[PATH_MAX + 1];
  60.   register char *pathp;
  61.   struct stat st;
  62.  
  63.   pathp = &path[sizeof (path)];
  64.   *--pathp = '\0';
  65.  
  66.   if (stat (".", &st) < 0)
  67.     return (NULL);
  68.  
  69.   thisdev = st.st_dev;
  70.   thisino = st.st_ino;
  71.  
  72.   if (stat ("/", &st) < 0)
  73.     return (NULL);
  74.  
  75.   rootdev = st.st_dev;
  76.   rootino = st.st_ino;
  77.  
  78.   while (!(thisdev == rootdev && thisino == rootino))
  79.     {
  80.       register DIR *dirstream;
  81.       register struct dirent *d;
  82.       dev_t dotdev;
  83.       ino_t dotino;
  84.       char mount_point;
  85.  
  86.       /* Move up a directory.  */
  87.       if (chdir ("..") < 0)
  88.     {
  89.       if (pathp != &path[sizeof (path) - 1])
  90.         {
  91.           /* Try to get back to the original directory.
  92.          This is the only place where this is possible.  */
  93.           int save = errno;
  94.           (void) chdir (pathp);
  95.           errno = save;
  96.         }
  97.       return (NULL);
  98.     }
  99.  
  100.       /* Figure out if this directory is a mount point.  */
  101.       if (stat(".", &st) < 0)
  102.     return (NULL);
  103.  
  104.       dotdev = st.st_dev;
  105.       dotino = st.st_ino;
  106.       mount_point = (dotdev != thisdev);
  107.  
  108.       /* Search for the last directory.  */
  109.       dirstream = opendir(".");
  110.       if (dirstream == NULL)
  111.     return (NULL);
  112.  
  113.       while ((d = readdir(dirstream)) != NULL)
  114.     {
  115.       if (d->d_name[0] == '.' &&
  116.           (d->d_name[1] == 0 ||
  117.            (d->d_name[2] == 0 && d->d_name[1] == '.')))
  118.         continue;
  119.  
  120.       /* if (mount_point || d->d_fileno == thisino) */
  121.       if (mount_point || d->d_ino == thisino)
  122.         {
  123.           if (stat(d->d_name, &st) < 0)
  124.         {
  125.           int save = errno;
  126.           (void) closedir(dirstream);
  127.           errno = save;
  128.           return (NULL);
  129.         }
  130.  
  131.           if (st.st_dev == thisdev && st.st_ino == thisino)
  132.         break;
  133.         }
  134.     }
  135.  
  136.       if (d == NULL)
  137.     {
  138.       int save = errno;
  139.       (void) closedir (dirstream);
  140.       errno = save;
  141.       return (NULL);
  142.     }
  143.       else
  144.     {
  145.       int d_namlen=strlen(d->d_name); /* new line */
  146.       pathp -= d_namlen;
  147.       (void) memcpy(pathp, d->d_name, d_namlen);
  148.       *--pathp = '/';
  149.       (void) closedir (dirstream);
  150.     }
  151.  
  152.       thisdev = dotdev;
  153.       thisino = dotino;
  154.     }
  155.  
  156.   if (pathp == &path[sizeof (path) - 1])
  157.     *--pathp = '/';
  158.  
  159.   if (chdir (pathp) < 0)
  160.     return (NULL);
  161.  
  162.   {
  163.     size_t len = &path[sizeof (path)] - pathp;
  164.     if (buf == NULL)
  165.       {
  166.     if (len < (size_t) size)
  167.       len = size;
  168.     buf = (char *) malloc (len);
  169.     if (buf == NULL)
  170.       return (NULL);
  171.       }
  172.     else if ((size_t) size < len)
  173.       {
  174.     errno = ERANGE;
  175.     return (NULL);
  176.       }
  177.     (void) memcpy ((char *) buf, (char *) pathp, len);
  178.   }
  179.  
  180.   return (buf);
  181. }
  182.